/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.origin;

/**
 * 一个接口，可以被实现于那些能通过给定键查找 {@link Origin} 信息的对象。可用于为现有类添加来源支持。
 *
 * @param <K> 查找键的类型
 * @author Phillip Webb
 * @since 2.0.0
 */
@FunctionalInterface
public interface OriginLookup<K> {

	/**
	 * 返回给定键的来源，如果无法确定来源则返回 {@code null}。
	 * @param key 要查找的键
	 * @return 键的来源或 {@code null}
	 */
	Origin getOrigin(K key);

	/**
	 * 如果该查找是不可变的且内容永远不会改变，则返回 {@code true}。
	 * @return 查找是否不可变
	 * @since 2.2.0
	 */
	default boolean isImmutable() {
		return false;
	}

	/**
	 * 返回执行查找时隐式应用的前缀，如果不使用前缀则返回 {@code null}。
	 * 前缀可用于区分那些可能冲突的键。例如，如果多应用程序运行在同一机器上，可以为每个应用设置不同前缀，确保使用不同的环境变量。
	 * @return 查找类应用的前缀或 {@code null}
	 * @since 2.5.0
	 */
	default String getPrefix() {
		return null;
	}

	/**
	 * 尝试从给定源中查找来源。如果源不是 {@link OriginLookup} 类型，或者查找过程中发生异常，则返回 {@code null}。
	 * @param source 源对象
	 * @param key 要查找的键
	 * @param <K> 键类型
	 * @return {@link Origin} 或 {@code null}
	 */
	@SuppressWarnings("unchecked")
	static <K> Origin getOrigin(Object source, K key) {
		if (!(source instanceof OriginLookup)) {
			return null;
		}
		try {
			return ((OriginLookup<K>) source).getOrigin(key);
		}
		catch (Throwable ex) {
			return null;
		}
	}

}
